// Copyright 2023 Huawei Cloud Computing Technology Co., Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef VIDEO_TCP_SOCET_AGENT_H
#define VIDEO_TCP_SOCET_AGENT_H

#include <memory>
#include <mutex>
#include <queue>
#include "VideoEncoder.h"
#include "Communication/Socket/VmiSocket.h"
#include "Communication/Socket/TcpSocket/VmiTcpServerSocket.h"
#include "Communication/Heartbeat/Heartbeat.h"
#include "Communication/StreamParse/StreamParser.h"
#include "Communication/MsgFragment/MsgFragment.h"
#include "Communication/NetComm/NetComm.h"

class ServerNotice : public VmiEventNotice {
public:
    /**
     * @功能描述：服务器监听socket异常回调通知，会重启Agent流程
     * @参数 [in] socket：服务端socket
     */
    virtual void Notice(std::shared_ptr<VmiSocket> socket);

    /**
     * @功能描述：ServerNotice构造函数
     */
    ServerNotice();

    /**
     * @功能描述：ServerNotice虚析构函数
     */
    virtual ~ServerNotice();
};

class VmiClientService : public VmiServerService {
public:
    /**
     * @功能描述：VmiClientService构造函数
     */
    VmiClientService();

    /**
     * @功能描述：VmiClientService析构函数
     */
    ~VmiClientService();

    /**
     * @功能描述：TCP服务端有新socket连接上时回调函数
     * @参数 [in] socket：新连接的客户端socket
     */
    virtual void Callback(std::shared_ptr<VmiSocket> socket);
};

class VideoSocketAgent {
public:
    /**
     * @功能描述：VideoSocketAgent的单例函数
     */
    static std::shared_ptr<VideoSocketAgent> GetInstance();

    /**
     * @功能描述：VideoSocketAgent的单例销毁函数
     */
    static void CloseInstance();

    /**
     * @功能描述：VideoSocketAgent的构造函数
     */
    VideoSocketAgent();
    /**
     * @功能描述：VideoSocketAgent的析构函数
     */
    virtual ~VideoSocketAgent();

    /**
     * @功能描述：启动TCP服务端,WebSocket服务器监听
     * @返回值：true代表启动socket server成功， failed代表失败
     */
    bool StartServer(int port);

    /**
     * @功能描述：设置客户端Socket对象，启动解析线程和重新心跳线程
     * @参数 [in] socket：客户端socket对象
     */
    void SetClientSocket(std::shared_ptr<VmiSocket> socket);

    /**
    * @功能描述：设置客户端Socket对象，启动解析线程和重新心跳线程
    * @参数 [in] data：数据地址
    * @参数 [in] length:数据长度
     */
    static uint32_t EncodeParamHandleHook(uint8_t* data, uint32_t length);

    static uint32_t YuvHandleHook(uint8_t* data, uint32_t length);//0206
    /**
     * @功能描述：重置VideoSocketAgent对象为初始态
     */
    void Reset();
    /**
     * @功能描述：处理SOCKET中断事件
     */
    void HandleSocketBreak(std::shared_ptr<NetComm> breakComm);

    /**
     * @功能描述：设置m_sendFlag变量为true。当调用Send函数时使能socket发送
     */
    void EnableSend();

    /**
     * @功能描述：设置m_sendFlag变量为false。当调用Send函数时禁用socket发送
     */
    void DisableSend();

    /**
     * @功能描述：VideoSocketAgent的socket发送函数。根据m_sendFlag标志可能不发送真正数据
     * @参数 [in] type：消息包类型
     * @参数 [in] pPkt：消息包头指针
     * @参数 [in] dataSize：消息包类型
     * @参数 [out] 参数名：消息包体大小
     * @返回值：返回已发送的数据大小
     */
    virtual int Send(VMIMsgType type, StreamMsgHead& pPkt, int dataSize);

    /**
     * @功能描述：获取YUV或参数配置数据
     */
    VideoData GetNextVideoData();

    /**
     * @功能描述：清理YUV和参数配置
     */
    void ClearVideoData();

private:
    /**
     * @功能描述：重置VideoSocketAgent对象为初始态
     */
    void Reset(std::shared_ptr<NetComm> breakComm);

    /**
     * @功能描述：设置新socket的连接, 初始化netCom
     */
    bool StartNewClient(std::shared_ptr<VmiSocket> newSocket);

    void AddVideoData(VideoData &videoData);

    std::shared_ptr<VideoEncoder> m_videoEncoder = nullptr; //0206
    std::shared_ptr<NetComm> m_videoagentComm = nullptr;
    std::shared_ptr<ServerNotice> m_serverNotive = nullptr;
    std::shared_ptr<VmiClientService> m_clientService = nullptr;
    VmiTcpServerSocket* m_serverSocket = nullptr;
    volatile bool m_sendFlag = false;
    std::mutex m_lock{};
    static std::shared_ptr<VideoSocketAgent> g_videoSockAgentInstance;
    static std::mutex g_instanceLock;

    std::queue<VideoData> m_videoDataQueue;
    std::mutex m_queueMutex {};

    class Garbo {
    public:
        /**
         * @功能描述：Garbo析构函数,删除单例g_instance
         */
        ~Garbo();
    };

    static Garbo g_garbo;
};

#endif
